package com.jiangyao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jiangyao.common.ApiResult;
import com.jiangyao.common.constants.CacheConstants;
import com.jiangyao.common.exception.ServerException;
import com.jiangyao.common.utils.DateUtil;
import com.jiangyao.common.utils.MD5util;
import com.jiangyao.common.utils.StringUtils;
import com.jiangyao.common.utils.ValidateUtil;
import com.jiangyao.component.RedisComponent;
import com.jiangyao.dao.*;
import com.jiangyao.model.dto.UserDto;
import com.jiangyao.model.dto.backend.JobUserDto;
import com.jiangyao.model.dto.backend.UserResumeDTO;
import com.jiangyao.model.dto.backend.UserSearchDTO;
import com.jiangyao.model.vo.AdminUserSessionVO;
import com.jiangyao.model.vo.JobVo;
import com.jiangyao.model.vo.UserDynamicVo;
import com.jiangyao.model.entity.*;
import com.jiangyao.model.vo.UserSessionVO;
import com.jiangyao.model.vo.backend.JobUserVO;
import com.jiangyao.model.vo.backend.UserBaseVO;
import com.jiangyao.model.vo.backend.UserResumeVO;
import com.jiangyao.service.ClassUserService;
import com.jiangyao.service.LoginLogService;
import com.jiangyao.service.UserService;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.codec.digest.Md5Crypt;
import org.checkerframework.checker.units.qual.A;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 成员表 服务实现类
 * </p>
 *
 * @author xiangyan
 * @since 2020-08-11
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<IUserDao, User> implements UserService {

    @Autowired
    private DozerBeanMapper dozerBeanMapper;

    @Autowired
    private RedisComponent redisComponent;

    @Autowired
    private LoginLogService loginLogService;

    @Autowired
    private IJobDao jobDao;

    @Autowired
    private IUserExperienceDao userExperienceDao;

    @Autowired
    private IProgressDetailDao progressDao;

    @Autowired
    private ClassUserService classUserService;

    @Autowired
    private IResumeSendDao iResumeSendDao;

    @Autowired
    private IResumeDao iResumeDao;

    @Autowired
    private IPublicProgressDetailDao publicProgressDetailDao;

    @Autowired
    private IUserDao iUserDao;

    public boolean checkVerificationCode(String phone ,String verification){
        String code = redisComponent.getObject(CacheConstants.CACHE_KEY_TOKEN_API_VERIFICATION + phone);
        boolean isCheck = verification.equals(code);
        if(isCheck){
            redisComponent.del(CacheConstants.CACHE_KEY_TOKEN_API_VERIFICATION + phone);
        }
        return isCheck;
    }

    @Override
    public UserSessionVO login(UserDto userDto) {
        if(!checkVerificationCode(userDto.getUserPhone(),userDto.getVerification())){
            throw new ServerException(301, "验证码验证失败");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_phone", userDto.getUserPhone());
        queryWrapper.last(" LIMIT 1");
        User user = this.getOne(queryWrapper);
        if (user == null) {
            throw new ServerException(302, "用户未注册");
        }
        UserSessionVO userSessionVO = dozerBeanMapper.map(user, UserSessionVO.class);
        setUserOrgAndClass(userSessionVO);
        // 登录token
        String token = UUID.randomUUID().toString();
        System.out.println("token-------"+token);
        userSessionVO.setToken(token);
        LoginLog loginLog = LoginLog.builder().userId(userSessionVO.getUserId()).token(token).userType(2).build();
        loginLogService.saveLoginLog(loginLog);

        redisComponent.set(CacheConstants.CACHE_KEY_TOKEN_API_PREFIX + token, userSessionVO, CacheConstants.CACHE_TIME_7_DAY);
        return userSessionVO;
    }

    @Override
    public UserSessionVO loginOpenId(UserDto userDto) {
        if(StringUtils.isBlank(userDto.getOpenId())){
            throw new ServerException(305, "未传入微信信息");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("open_id", userDto.getOpenId());
        queryWrapper.last(" LIMIT 1");
        User user = this.getOne(queryWrapper);
        if (user == null) {
            throw new ServerException(302, "用户未注册");
        }
        UserSessionVO userSessionVO = dozerBeanMapper.map(user, UserSessionVO.class);
        setUserOrgAndClass(userSessionVO);
        // 登录token
        String token = UUID.randomUUID().toString();
        System.out.println("token-------"+token);
        userSessionVO.setToken(token);
        LoginLog loginLog = LoginLog.builder().userId(userSessionVO.getUserId()).token(token).userType(2).build();
        loginLogService.saveLoginLog(loginLog);

        redisComponent.set(CacheConstants.CACHE_KEY_TOKEN_API_PREFIX + token, userSessionVO, CacheConstants.CACHE_TIME_7_DAY);
        return userSessionVO;
    }

    @Override
    public UserSessionVO loginPhoneIdCard(UserDto userDto) {
        User result = null;
        String temp=userDto.getPassword().toUpperCase();
        String MD5Pwd = MD5util.generateSymbol(temp); //added by leelv
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_phone", userDto.getUserPhone());
        queryWrapper.eq("password",MD5Pwd);
        queryWrapper.last(" LIMIT 1");
        result = this.getOne(queryWrapper);
        if(result==null) {
            QueryWrapper<User> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.eq("id_card", userDto.getIdCard().toUpperCase()); //added by leelv
            queryWrapper2.eq("password", MD5Pwd);
            queryWrapper2.last(" LIMIT 1");
            result = this.getOne(queryWrapper2);
        }
        if(result==null){
            throw new ServerException(301, "账号密码不正确");
        }
        UserSessionVO userSessionVO = dozerBeanMapper.map(result, UserSessionVO.class);
        // 登录token
        String token = UUID.randomUUID().toString();
        System.out.println("token-------"+token);
        userSessionVO.setToken(token);
        LoginLog loginLog = LoginLog.builder().userId(userSessionVO.getUserId()).token(token).userType(2).build();
        loginLogService.saveLoginLog(loginLog);

        redisComponent.set(CacheConstants.CACHE_KEY_TOKEN_API_PREFIX + token, userSessionVO, CacheConstants.CACHE_TIME_10_MINUTE);
        return userSessionVO;
    }

    private void setUserOrgAndClass(UserSessionVO userSessionVO){
        QueryWrapper<ClassUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userSessionVO.getUserId()).eq("status",1);
        List<ClassUser> list = classUserService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        Map<Integer, ClassUser> orgMap = list.stream().collect(Collectors.toMap(ClassUser::getOrgId, a -> a,(k1, k2)->k1));
        userSessionVO.setOrgIdList( new ArrayList<>( orgMap.keySet()));
        Map<Integer, ClassUser> classMap = list.stream().collect(Collectors.toMap(ClassUser::getClassId, a -> a,(k1, k2)->k1));
        userSessionVO.setClassIdList(new ArrayList<>(classMap.keySet()));
    }

    @Override
    public UserSessionVO register(UserDto userDto) {
        if(!checkVerificationCode(userDto.getUserPhone(),userDto.getVerification())){
            throw new ServerException(301, "验证码验证失败");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_phone", userDto.getUserPhone());
        queryWrapper.last(" LIMIT 1");
        User existUser = this.getOne(queryWrapper);
        if (existUser != null) {
            throw new ServerException(303, "用户已注册");
        }
        if(!ValidateUtil.checkIdCardNo(userDto.getIdCard())) {
            throw new ServerException(304, "无效身份证号");
        }

        String MD5Pwd = MD5util.generateSymbol(userDto.getIdCard().substring(12,18));
        User user = dozerBeanMapper.map(userDto, User.class);
        user.setCreateTime(new Date());
        user.setRegFrom(1);
        user.setPassword(MD5Pwd);
        this.save(user);
        UserSessionVO userSessionVO = dozerBeanMapper.map(user, UserSessionVO.class);
        // 登录token
        String token = UUID.randomUUID().toString();
        System.out.println("token-------"+token);
        userSessionVO.setToken(token);
        LoginLog loginLog = LoginLog.builder().userId(userSessionVO.getUserId()).token(token).userType(2).build();
        loginLogService.saveLoginLog(loginLog);

        redisComponent.set(CacheConstants.CACHE_KEY_TOKEN_API_PREFIX + token, userSessionVO, CacheConstants.CACHE_TIME_10_MINUTE);
        return userSessionVO;
    }

    @Override
    public UserSessionVO registerIdCard(UserDto userDto) {
        if(!ValidateUtil.checkIdCardNo(userDto.getIdCard())) {//需修改
            throw new ServerException(304, "无效身份证号");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_phone", userDto.getUserPhone());
        queryWrapper.last(" LIMIT 1");
        QueryWrapper<User> queryWrapperIdCard = new QueryWrapper<>();
        queryWrapperIdCard.eq("id_card", userDto.getIdCard().toUpperCase());//added by leelv
        queryWrapperIdCard.last(" LIMIT 1");
        User existUserPhone = this.getOne(queryWrapper);
        User existUserIdCard = this.getOne(queryWrapperIdCard);
        if (existUserPhone != null) {
            throw new ServerException(311, "该手机号码已存在请使用账号登录");
        }
        if (existUserIdCard != null) {
            throw new ServerException(312, "该身份证号已存在请使用账号登录");
        }
        String MD5Pwd = MD5util.generateSymbol(userDto.getIdCard().toUpperCase().substring(12,18)); //added by leelv
        User user = dozerBeanMapper.map(userDto, User.class);
        user.setCreateTime(new Date());
        user.setRegFrom(1);
        user.setPassword(MD5Pwd);
        this.save(user);
        UserSessionVO userSessionVO = dozerBeanMapper.map(user, UserSessionVO.class);
        // 登录token
        String token = UUID.randomUUID().toString();
        System.out.println("token-------"+token);
        userSessionVO.setToken(token);
        LoginLog loginLog = LoginLog.builder().userId(userSessionVO.getUserId()).token(token).userType(2).build();
        loginLogService.saveLoginLog(loginLog);

        redisComponent.set(CacheConstants.CACHE_KEY_TOKEN_API_PREFIX + token, userSessionVO, CacheConstants.CACHE_TIME_10_MINUTE);
        return userSessionVO;
    }



    @Override
    public List<UserDynamicVo> getUserDynamic() {
        List<UserDynamicVo> result = new ArrayList<>();

//        QueryWrapper<Job> jobParam = new QueryWrapper<Job>();
//        jobParam.isNotNull("create_time").eq("status","1").orderByDesc("job_id").last("limit 8");
//        List<Job> jobList = jobDao.selectList(jobParam);
//        for(Job obj :jobList){
//            result.add(new UserDynamicVo(1,obj.getJobId(),obj.getJobName(),obj.getCreateTime()));
//        }
//
//        QueryWrapper<UserExperience> expParam = new QueryWrapper<>();
//        expParam.isNotNull("audit_time").eq("user_id",getLoginApiUserId()).eq("status","2").orderByDesc("audit_time").last("limit 8");
//        List<UserExperience> experienceList = userExperienceDao.selectList(expParam) ;
//        for(UserExperience obj :experienceList){
//            result.add(new UserDynamicVo(1,obj.getId(),obj.getContent(),obj.getAuditTime()));
//        }
//
//        ProgressDetail params = new ProgressDetail();
//        params.setUserId(getLoginApiUserId());
//        List<UserDynamicVo> progressDetails = progressDao.getProcessDynamic(params);
//        result.addAll(progressDetails);

        PublicProgressDetail params = new PublicProgressDetail();
        params.setUserId(getLoginApiUserId());
        List<UserDynamicVo> progressDetails = publicProgressDetailDao.getPublicProcessDynamic(params);
        result.addAll(progressDetails);

        Collections.sort(result);
        return result;
    }

    @Override
    public PageInfo<JobUserVO> getJobUserList(JobUserDto jobUserDto) {
        PageHelper.startPage(jobUserDto.getPageNo(),jobUserDto.getPageSize());
        QueryWrapper<ResumeSend> resumeSendQueryWrapper = new QueryWrapper<>();
        resumeSendQueryWrapper.eq("job_id",jobUserDto.getJobId())
                .eq("org_id",jobUserDto.getOrgId());
        resumeSendQueryWrapper.orderByDesc("send_id");
        List<ResumeSend> resumeSends = iResumeSendDao.selectList(resumeSendQueryWrapper);
        ArrayList<JobUserVO> jobUserList = new ArrayList<>();

        for (ResumeSend resumeSend : resumeSends) {
            QueryWrapper<Resume> resumeQueryWrapper = new QueryWrapper<>();
            resumeQueryWrapper.eq("resume_id",resumeSend.getResumeId());
            if(StringUtils.isNotEmpty(jobUserDto.getSearchVal())){
                resumeQueryWrapper.like("name",jobUserDto.getSearchVal());
            }
            Resume resume = iResumeDao.selectOne(resumeQueryWrapper);
            if(null !=resume){
                long differDays=0L;
                Date endTime=null;
                //获取用户工作年限
                QueryWrapper<UserExperience> userExperienceQueryWrapper = new QueryWrapper<>();
                userExperienceQueryWrapper.eq("user_id",resume.getUserId()).eq("type",2);
                List<UserExperience> userExperiences = userExperienceDao.selectList(userExperienceQueryWrapper);
                for (UserExperience userExperience : userExperiences) {
                    endTime = userExperience.getEndTime();
                    if (null == endTime){
                        endTime =  new Date();
                    }
                    differDays += DateUtil.between(userExperience.getStartTime(), endTime);
                }
                int workingLife = (int) Math.floor(differDays / 365);
                JobUserVO jobUserVO = new JobUserVO();
                jobUserVO.setUserId(resumeSend.getUserId());
                jobUserVO.setName(resume.getName());
                jobUserVO.setAge(getAge(resume.getBirthday()));
                jobUserVO.setEducation(resume.getEducation());
                jobUserVO.setDeliveryTime(resume.getCreateTime());
                jobUserVO.setSendId(resumeSend.getSendId());
                jobUserVO.setResumeId(resumeSend.getResumeId());
                jobUserVO.setWorkingLife(workingLife);
                jobUserList.add(jobUserVO);
            }
        }
        PageInfo<JobUserVO> pageInfo = new PageInfo(jobUserList);
        return pageInfo;
    }

    @Override
    public UserResumeVO getUserResume(UserResumeDTO userResumeDTO) {
        //更改为已查看状态
        QueryWrapper<ResumeSend> resumeSendQueryWrapper = new QueryWrapper<>();
        resumeSendQueryWrapper.eq("send_id",userResumeDTO.getSendId());
        ResumeSend resumeSend = iResumeSendDao.selectOne(resumeSendQueryWrapper);
        if(resumeSend.getDeliveryStatus() == 0){
            resumeSend.setDeliveryStatus(1);
            iResumeSendDao.updateById(resumeSend);
        }

        //获取用户信息
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("user_id",userResumeDTO.getUserId());
        User user = iUserDao.selectOne(userQueryWrapper);
        //获取投递的快照简历
        UserResumeVO userResumeVO = new UserResumeVO();
        QueryWrapper<Resume> resumeQueryWrapper = new QueryWrapper<>();
        resumeQueryWrapper.eq("resume_id", userResumeDTO.getResumeId());
        Resume resume = iResumeDao.selectOne(resumeQueryWrapper);
        //获取个人经历
        QueryWrapper<UserExperience> userExperienceQueryWrapper = new QueryWrapper<>();
        userExperienceQueryWrapper.eq("user_id",userResumeDTO.getUserId());
        List<UserExperience> userExperiences = userExperienceDao.selectList(userExperienceQueryWrapper);
        ArrayList<UserExperience> educationExperienceList = new ArrayList<>();
        ArrayList<UserExperience> workExperienceList = new ArrayList<>();
        ArrayList<UserExperience> ertificateSkillsLIstanbul = new ArrayList<>();
        ArrayList<UserExperience> awardList = new ArrayList<>();
        for (UserExperience userExperience : userExperiences) {
            if(userExperience.getType().equals(1)){
                educationExperienceList.add(userExperience);
            }else if(userExperience.getType().equals(2)){
                workExperienceList.add(userExperience);
            }else if(userExperience.getType().equals(3)){
                ertificateSkillsLIstanbul.add(userExperience);
            }else if(userExperience.getType().equals(4)){
                awardList.add(userExperience);
            }
        }
        userResumeVO.setUserId(user.getUserId());
        userResumeVO.setName(user.getUserName());
        userResumeVO.setHeadImg("空");
        userResumeVO.setIntegralNum(user.getIntegralNum());
        userResumeVO.setUserId(user.getUserId());
        userResumeVO.setResume(resume);
        userResumeVO.setEducationExperienceList(educationExperienceList);
        userResumeVO.setWorkExperienceList(workExperienceList);
        userResumeVO.setErtificateSkillsLIstanbul(ertificateSkillsLIstanbul);
        userResumeVO.setAwardList(awardList);
        userResumeVO.setDeliveryStatus(resumeSend.getDeliveryStatus());
        userResumeVO.setStatus(resumeSend.getStatus());
        return userResumeVO;
    }

    public static  int getAge(Date birthDay){
        Calendar cal = Calendar.getInstance();
        if (cal.before(birthDay)) { //出生日期晚于当前时间，无法计算
            throw new IllegalArgumentException(
                    "出生日期晚于当前时间，无法计算");
        }
        int yearNow = cal.get(Calendar.YEAR);  //当前年份
        int monthNow = cal.get(Calendar.MONTH);  //当前月份
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); //当前日期
        cal.setTime(birthDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        int age = yearNow - yearBirth;   //计算整岁数
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) age--;//当前日期在生日之前，年龄减一
            }else{
                age--;//当前月份在生日之前，年龄减一
            }
        }
        return age;
    }

    @Override
    public List<UserBaseVO> searchForSelect(UserSearchDTO searchDTO) {
        AdminUserSessionVO adminUserSessionVO = getAdminLoginSession();
        // 当前登录用户管理的组织ID集合(业务数据权限)
        searchDTO.setOrgIdList(adminUserSessionVO.getOrgIdList());
        // 当前登录用户管理的班级ID集合(业务数据权限)
        searchDTO.setClassIdList(adminUserSessionVO.getClassIdList());
        return iUserDao.searchForSelect(searchDTO);
    }
}
